﻿using Microsoft.AspNetCore.Http.Features;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MyCompany.MyProject.Common.Https;

/// <summary>
/// 扩展 HttpResponseStream <br/>
/// 原始[HttpResponseStream]实际上只是个包装类,内部包装了[HttpResponsePipeWriter]来进行写入响应数据
/// </summary>
public class FluentHttpResponseStream : Stream
{
    private readonly IHttpResponseBodyFeature pipeWrite;
    private readonly IHttpBodyControlFeature bodyControl;
    private readonly MemoryStream _stream = new();

    public FluentHttpResponseStream(IHttpResponseBodyFeature pipeWrite, IHttpBodyControlFeature bodyControl)
    {
        this.pipeWrite = pipeWrite;
        this.bodyControl = bodyControl;
    }
    public override bool CanRead => _stream.CanRead;

    public override bool CanSeek => _stream.CanSeek;

    public override bool CanWrite => _stream.CanWrite;

    public override long Length => _stream.Length;

    public override long Position { get => _stream.Position; set => _stream.Position = value; }

    public override void Flush()
    {
        if (!bodyControl.AllowSynchronousIO) throw new InvalidOperationException("SynchronousWritesDisallowed ");
        _stream.Flush();
    }

    public override int Read(byte[] buffer, int offset, int count)
    {
        return _stream.Read(buffer, offset, count);
    }

    public override long Seek(long offset, SeekOrigin origin)
    {
        return _stream.Seek(offset, origin);
    }

    public override void SetLength(long value)
    {
        _stream.SetLength(value);
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
       WriteAsync(buffer, offset, count,default).GetAwaiter().GetResult();
    }

    public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
    {
        _stream.Write(buffer, offset, count);
        return pipeWrite.Writer.WriteAsync(new ReadOnlyMemory<byte>(buffer, offset, count), cancellationToken).AsTask();
    }

    protected override void Dispose(bool disposing)
    {
        _stream?.Dispose();
        base.Dispose(disposing);
    }
}
